package me.shibor.study.javaSE.encryption.demo;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import me.shibor.study.javaSE.encryption.annotation.Encryption;
import me.shibor.study.javaSE.encryption.domain.Information;

public class EncryptionDemo1 {

    ObjectMapper objectMapper = new ObjectMapper();
    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";// 默认的加密算法
    private static final String password = "shibor123456";
    // 返回生成指定算法密钥生成器的 KeyGenerator 对象
    KeyGenerator kg;
    // 生成一个密钥
    static SecretKey secretKey;
    static SecretKeySpec secretKeySpec;

    {
        try {
            // 返回生成指定算法密钥生成器的 KeyGenerator 对象
            kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // AES 要求密钥长度为 128
        kg.init(128, new SecureRandom(password.getBytes()));
        // 生成一个密钥
        secretKey = kg.generateKey();
        // 生成加密秘钥
        secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
    }

    public void doData(Object obj) throws IllegalArgumentException, IllegalAccessException, JsonProcessingException {

        Class<?> clazz = obj.getClass();

        System.out.println("clazz: " + clazz);
        Field[] fields = clazz.getDeclaredFields();

        Map<String, Object> vars = new HashMap<String, Object>();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().getName().equals(Encryption.class.getName())) {
                    field.setAccessible(true);
                    vars.put(field.getName(), field.get(obj));
                }
            }
        }
        System.out.println("vars: " + vars);
//        String dataJson = objToJacksonString(vars);
        Gson gson = new  Gson();
        String dataJson = gson.toJson(vars);
        System.out.println("dataJson: " + dataJson);

        ((Information) obj).setScretMessage(dataJson);

        System.out.println("obj: " + obj);
    }

  public void doDataBack(Object obj) throws JsonParseException, JsonMappingException, IOException {

      Class<?> clazz = obj.getClass();
      
      String jsonString = ((Information) obj).getScretMessage();

      HashMap<String, Object> jacksonToMap = jacksonToMap(jsonString);
      System.out.println("jacksonToMap: " + jacksonToMap);
      Field[] fields = clazz.getDeclaredFields();

      for (Field field : fields) {
          Annotation[] annotations = field.getAnnotations();
          for (Annotation annotation : annotations) {
              if (annotation.annotationType().getName().equals(Encryption.class.getName())) {
                  field.setAccessible(true);
                  try {
                      
                      if(Date.class.equals(field.getType())) {
                          System.out.println("" + field.getType());
                          Date date = new Date((String)jacksonToMap.get(field.getName()));
                          field.set(obj,date);
                      }else {
                          field.set(obj,jacksonToMap.get(field.getName()));
                      }
                      
                   
                } catch (Exception e) {
                    e.printStackTrace();
                }
              }
          }
      }
      
//      String setMethod = "";
//      String key = "";
//      for (Map.Entry<String, Object> entry : jacksonToMap.entrySet()) {
//
//          System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
//          key = entry.getKey();
//          setMethod = "set" + key.substring(0, 1).toUpperCase() + key.substring(1, key.length());
//
//          try {
//              obj.getClass().getMethod(setMethod, entry.getValue().getClass()).invoke(obj, entry.getValue());
//          } catch (Exception e) {
//              e.printStackTrace();
//          }
//
//      }
  }
    
//    public void doDataBack(Object obj) throws JsonParseException, JsonMappingException, IOException {
//
//        String jsonString = ((Information) obj).getScretMessage();
//
//        HashMap<String, Object> jacksonToMap = jacksonToMap(jsonString);
//        System.out.println("jacksonToMap: " + jacksonToMap);
//        String setMethod = "";
//        String key = "";
//        for (Map.Entry<String, Object> entry : jacksonToMap.entrySet()) {
//
//            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
//            key = entry.getKey();
//            setMethod = "set" + key.substring(0, 1).toUpperCase() + key.substring(1, key.length());
//
//            try {
//                obj.getClass().getMethod(setMethod, entry.getValue().getClass()).invoke(obj, entry.getValue());
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//
//        }
//    }

    public String objToJacksonString(Object obj) throws JsonProcessingException {
        return objectMapper.writeValueAsString(obj);
    }

    @SuppressWarnings("unchecked")
    public HashMap<String, Object> jacksonToMap(String json)
            throws JsonParseException, JsonMappingException, IOException {
        return objectMapper.readValue(json, HashMap.class);
    }

    /**
     * 加密
     */
    public String encrypt(String content) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            return Base64.encodeBase64String(result);// 通过Base64转码返回
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * AES 解密操作
     * 
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public static String decrypt(String content, String password) {
        try {
            // 实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            // 使用密钥初始化，设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

            // 执行操作
            byte[] result = cipher.doFinal(Base64.decodeBase64(content));

            return new String(result, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

}
